package com.clss.webrtclibrary;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.view.ViewGroup;

import org.webrtc.EglBase;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon;
import org.webrtc.SurfaceViewRenderer;

import static com.clss.webrtclibrary.KurentoServer.WEBRTC_TYPE_SENDRECV;

/**
 * 加入在线视频房间
 * @author liuv
 * @date 2018/5/2
 */

public class LiveVideoRoom {
    private static final String TAG = "LiveVideoRoom";
    public static final int LIVE_VIDEO_TYPE_NORMAL = 0; //普通视频
    public static final int LIVE_VIDEO_TYPE_SILENCE = 1; //静默视频，关闭对方声音
    public static final int LIVE_VIDEO_TYPE_VOICE = 2; //语音视频
    public static final int LIVE_VIDEO_TYPE_CALL = 3; //警民直连视频

    private MediaInfoBean mMediaInfoBean;
    private Context mContext;
    private KurentoServer mKurentoServer;
    private KurentoMediaCallback mKurentoMediaCallback;
    private EglBase mEglBase;
    private ProxyVideoSink mSmallProxyVideoSink = new ProxyVideoSink();
    private ProxyVideoSink mFullProxyVideoSink = new ProxyVideoSink();
    private SurfaceViewRenderer mFullRenderer, mSmallRenderer;
    private boolean isLocalFrameInFullScreen = true, isRemoteEnable = false;
    private IVideoRoomListener mIVideoRoomListener;
    private int mRemoteDefaultHight, mRemoteDefaultWidth;
    private Activity mActivity;
    private MediaStream mRemoteMediaStream = null;
    private MediaStream mTempRemoteMediaStream = null; //为报警转接功能服务，临时存在
    private boolean mNeedSound, mRemoteVideoTrackEnable, mLocalVideoTrackEnable = true;
    private String mTempRomoteId;
    private Intent mScreenIntent;

    public LiveVideoRoom(MediaInfoBean mediaInfoBean, SurfaceViewRenderer fullRenderer,
                         SurfaceViewRenderer smallRenderer, Integer videoType,
                         IVideoRoomListener IVideoRoomListener, Intent intent){
        this.mMediaInfoBean = mediaInfoBean;
        this.mIVideoRoomListener = IVideoRoomListener;
        this.mContext = mIVideoRoomListener.getContext();
        this.mEglBase = EglBase.create();
        this.mFullRenderer = fullRenderer;
        this.mSmallRenderer = smallRenderer;
        this.mActivity = (Activity) mContext;
        this.mScreenIntent = intent;
        initRoom(videoType);
    }

    public LiveVideoRoom(MediaInfoBean mediaInfoBean, SurfaceViewRenderer fullRenderer,
                         SurfaceViewRenderer smallRenderer, Integer videoType,
                         IVideoRoomListener IVideoRoomListener) {
        this(mediaInfoBean, fullRenderer, smallRenderer, videoType, IVideoRoomListener,null);
    }

    private void initRoom(int videoType){
        switch (videoType){
            case LIVE_VIDEO_TYPE_NORMAL:
                this.mNeedSound = true;
                this.mRemoteVideoTrackEnable = true;
                this.mLocalVideoTrackEnable = true;
                break;
            case LIVE_VIDEO_TYPE_SILENCE:
                this.mNeedSound = false;
                this.mRemoteVideoTrackEnable = true;
                this.mLocalVideoTrackEnable = true;
                break;
            case LIVE_VIDEO_TYPE_VOICE:
                this.mNeedSound = true;
                this.mRemoteVideoTrackEnable = false;
                this.mLocalVideoTrackEnable = false;
                break;
            case LIVE_VIDEO_TYPE_CALL:
                this.mNeedSound = true;
                this.mRemoteVideoTrackEnable = true;
                this.mLocalVideoTrackEnable = false;
                break;
        }

        mSmallRenderer.init(mEglBase.getEglBaseContext(), null);
        mSmallRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
        mSmallRenderer.setEnableHardwareScaler(true);

        mFullRenderer.init(mEglBase.getEglBaseContext(), null);
        mFullRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
        mFullRenderer.setEnableHardwareScaler(true);

        mSmallProxyVideoSink.setTarget(mSmallRenderer);
        mFullProxyVideoSink.setTarget(mFullRenderer);

        startVideo();

        mSmallRenderer.setOnClickListener(v -> switchFrames());
        ViewGroup.LayoutParams layoutParams = mSmallRenderer.getLayoutParams();
        mRemoteDefaultHight = layoutParams.height;
        mRemoteDefaultWidth = layoutParams.width;

    }

    private void startVideo(){
        mKurentoServer = new KurentoServer(mContext, WEBRTC_TYPE_SENDRECV,
                new KurentoGatewayCallback());
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        mKurentoServer.initializeMediaContext(options);
    }

    public boolean stopVideo(){
        if (mFullProxyVideoSink != null) {
            mFullProxyVideoSink.setTarget(null);
        }
        if (mSmallProxyVideoSink != null) {
            mSmallProxyVideoSink.setTarget(null);
        }
        if (mFullRenderer != null){
            mFullRenderer.release();
            mFullRenderer = null;
        }
        if (mSmallRenderer != null){
            mSmallRenderer.release();
            mSmallRenderer = null;
        }

        mFullProxyVideoSink = null;
        mSmallProxyVideoSink = null;
        mEglBase.release();
        return mKurentoServer.closeAllLiveVideo();
    }

    public boolean switchCamera(){
        return mKurentoServer.switchCamera();
    }

    public boolean switchFrames(){

        if (mFullProxyVideoSink.getTarget() == null && mSmallProxyVideoSink.getTarget() != null){
            return isLocalFrameInFullScreen;
        }
        if(mFullProxyVideoSink.getTarget() != null && mSmallProxyVideoSink.getTarget() == null){
            return isLocalFrameInFullScreen;
        }
        if (!isRemoteEnable){
            return isLocalFrameInFullScreen;
        }
        isLocalFrameInFullScreen = !isLocalFrameInFullScreen;
        mFullProxyVideoSink.setTarget(isLocalFrameInFullScreen ? mFullRenderer : mSmallRenderer);
        mSmallProxyVideoSink.setTarget(isLocalFrameInFullScreen ? mSmallRenderer : mFullRenderer);
        Lg.i(TAG, "---isLocalFrameInFullScreen===" + isLocalFrameInFullScreen);
        return isLocalFrameInFullScreen;
    }

    public AppRTCAudioManager.AudioDevice switchSoundOutput(){
        return mKurentoServer.switchSoundOutput();
    }

    private void showRemoteView(){
        ViewGroup.LayoutParams layoutParams = mSmallRenderer.getLayoutParams();
        layoutParams.height = mRemoteDefaultHight;
        layoutParams.width = mRemoteDefaultWidth;
        mActivity.runOnUiThread(() -> {
            mSmallRenderer.setLayoutParams(layoutParams);
        });
    }

    private void hideRemoteView(){
        ViewGroup.LayoutParams layoutParams = mSmallRenderer.getLayoutParams();
        layoutParams.height = 1;
        layoutParams.width = 1;
        mActivity.runOnUiThread(() -> {
            mSmallRenderer.setLayoutParams(layoutParams);
        });
    }

    public void setRemoteVoiceSwitch(boolean enable){
        if (mRemoteMediaStream != null){
            mRemoteMediaStream.audioTracks.get(0).setVolume(enable ? 10 : 0);
        }
    }

    /** 设置是否显示双方的画面 */
    public boolean setVideoTrackSwitch(boolean enable){
        mRemoteVideoTrackEnable = enable;
        if (mRemoteMediaStream != null){
            mRemoteMediaStream.videoTracks.get(0).setEnabled(enable);
        }

        mLocalVideoTrackEnable = enable;
        setVideoShowInRemote();
        return mRemoteVideoTrackEnable;
    }

    /** 设置是否显示本地画面给对方 */
    public boolean setVideoShowInRemote(){
        if (mLocalVideoTrackEnable){
            mKurentoServer.setVideoTrackEnable(false);
            mLocalVideoTrackEnable = false;
        }else {
            mKurentoServer.setVideoTrackEnable(true);
            mLocalVideoTrackEnable = true;
        }
        return mLocalVideoTrackEnable;
    }

    /** 收到新的信令 */
    public void receivedNewSign(KurentoSignallingBean receivedBean){
        if (mKurentoServer != null){
            mKurentoServer.receivedNewMessage(receivedBean);
        }
    }

    /**
     * 网关回调
     */
    private class KurentoGatewayCallback implements IKurentoGatewayCallback {

        @Override
        public MediaInfoBean getMediaInfo() {
            return mMediaInfoBean;
        }

        @Override
        public IKurentoMediaCallbacks getMediaHandleCallback() {
            return mKurentoMediaCallback == null ?
                    mKurentoMediaCallback = new KurentoMediaCallback()
                    : mKurentoMediaCallback;
        }

        @Override
        public EglBase getEglBase() {
            return mEglBase;
        }

        @Override
        public void webSocketDisconnect() {
            Lg.i(TAG, "---webSocketDisconnect===");
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.videoRoomDisconnect();
            }
        }

        @Override
        public void signalingParamError(String error) {
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.videoError(error);
            }
        }

        @Override
        public void arrivedRoom(KurentoSignallingBean signallingBean) {
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.newArrivedRoom(signallingBean);
            }
        }

        @Override
        public void leaveRoom(String id) {
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.leaveRoom();
            }
        }

        @Override
        public void showConnectionInfo(String info) {
            Lg.i(TAG, "---showConnectionInfo===" + info);
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.videoConnectionState(info.split(":")[1]);
            }
        }

        @Override
        public Boolean getVideoTrackEnable() {
            return mLocalVideoTrackEnable;
        }

        @Override
        public IVideoRoomListener getVideoRoomListener() {
            return mIVideoRoomListener;
        }
    }

    /**
     * media回调
     */
    public class KurentoMediaCallback implements IKurentoMediaCallbacks {

        @Override
        public void success(KurentoPeerManager handle) {

        }

        @Override
        public void onLocalStream(MediaStream stream) {
            Lg.i(TAG, "---onLocalStream===" + stream.audioTracks.size());
            if (mIVideoRoomListener != null){
                mIVideoRoomListener.videoOnStart();
            }
            if (stream.videoTracks.size() > 0) {
                stream.videoTracks.get(0).addSink(mFullProxyVideoSink);
            }
        }

        @Override
        public void onRemoteStream(MediaStream stream, String id) {
            Lg.i(TAG, "---onRemoteStream===" + id);
            if (mIVideoRoomListener != null && !TextUtils.isEmpty(id)){
                mIVideoRoomListener.remoteVideoIsEnable(id);
            }
            if (TextUtils.isEmpty(id)){
                return;
            }
            isRemoteEnable = true;
            if (mRemoteMediaStream == null) {
                mRemoteMediaStream = stream;
            }else {
                mTempRemoteMediaStream = stream;
                mRemoteMediaStream.videoTracks.get(0).removeSink(mSmallProxyVideoSink);
                mTempRomoteId = id;
            }
            if (!mNeedSound) {
                stream.audioTracks.get(0).setVolume(0);
            }
            stream.videoTracks.get(0).setEnabled(mRemoteVideoTrackEnable);
            stream.videoTracks.get(0).addSink(mSmallProxyVideoSink);
        }

        @Override
        public void onRemoveRemoteStream(String id) {
            Lg.i(TAG, "---onRemoveRemoteStream===" + id);
            if (id.equals(mTempRomoteId)){
                //转接没成功，后加入的接警台退出了
                mRemoteMediaStream.videoTracks.get(0).addSink(mSmallProxyVideoSink);
            }else {
                //转接成功，第一个接警台退出了
                mRemoteMediaStream = mTempRemoteMediaStream;
            }
            mTempRemoteMediaStream = null;
            mTempRomoteId = "";
        }

        @Override
        public void onDetached() {

        }

        @Override
        public Intent getScreenIntent() {
            return mScreenIntent;
        }

        @Override
        public void enableVideo(String id) {
            Lg.i(TAG, "---enableVideo===" + id);
            isRemoteEnable = true;
            showRemoteView();
        }

        @Override
        public void disableVideo(String id) {
            Lg.i(TAG, "---disableVideo===" + id);
            if (!isLocalFrameInFullScreen){
                switchFrames();
            }
            isRemoteEnable = false;
            hideRemoteView();
        }
    }
}
